<!-- 触摸裁剪图片 -->
<template>
	<view style="width: 300px;height: 350px;position: relative;">
		<view class='touch-clip-image' @mousedown="touchstart" @mousemove="touchmove" @mouseup="touchend"
			@touchstart="touchstart" @touchmove="touchmove" @touchend="touchend" :style="{
				width:width+'px',
				height:height+'px'
			}">
			<!-- 图片展示 -->
			<image class="image-wrap" :src="image" :style="{
						width: imageCanvasWidth + 'px',
						height: imageCanvasHeight + 'px'
					}" />
			<!-- 蒙层涂抹canvas -->
			<canvas ref="canvasPolygon" class="canvas-polygon" canvas-id="canvas-polygon" :style="{
							width: width +'px',
							 height: height +'px'
						}" disable-scroll />
			<!-- 裁剪canvas -->
			<canvas ref="canvasImage" class="canvas-image" canvas-id="canvas-image" :style="{
							width: width +'px',
							 height: height +'px'
						}" />
		</view>
		<!-- <view style="position: absolute;bottom: 0;width: 100%;">
			局部修改仅支持对3天内生成结果进行操作，过期不可用！
		</view> -->
		<view
			style="position: absolute;bottom: 0;width: 100%;display: flex;justify-content: flex-start;align-items: center;">
			<view style="width: 15%;font-weight: 500;font-size: 16px;">局部 修改</view>
			<view class="tool">
				<view>撤回</view>
				<view @click="clearCanavas">重做</view>
				<view>移动</view>
				<view>画笔</view>
				<view>橡皮擦</view>
			</view>
		</view>

	</view>


</template>

<script>
	export default {
		name: 'touch-clip-image',
		components: {},
		props: {
			image: { // 选择的图片
				type: String,
				default: ''
			},
			radius: { // 半径
				type: [Number, String],
				default: 5
			},
			alpha: { // 透明度
				type: [Number, String],
				default: 0.6
			},
			touchEndTodo: { // 是否触摸结束就裁剪
				type: Boolean,
				default: false
			},
			width: {
				type: [Number, String],
				default: 300
			},
			height: {
				type: [Number, String],
				default: 300
			},
		},
		data() {
			return {
				imageCanvasWidth: 0,
				imageCanvasHeight: 0,
				canvasPolygon: '',
				canvasImage: '',
				touchX: 0,
				touchY: 0,
				start: false,
				positionX: 0,
				positionY: 0,

			};
		},
		watch: {
			image() {
				if (this.image) {
					uni.getImageInfo({
						src: this.image,
						success: (res) => {
							this.imageDraw(res);
						},
						fail: (res) => {
							console.log(res);
						}
					});
				}
			}
		},
		// 组件创建完成
		created() {
			if (this.image) {
				uni.getImageInfo({
					src: this.image,
					success: (res1) => {
						this.imageDraw(res1);
					},
					fail: (res2) => {
						console.log(res2);
					}
				});
			}
		},
		// 组件挂载之后
		mounted() {
			this.$nextTick(() => {
				this.canvasPolygon = uni.createCanvasContext('canvas-polygon', this);
				this.canvasImage = uni.createCanvasContext('canvas-image', this);
				this.canvasPolygon.save();
				this.canvasImage.save();
				this.drawMonlayer();
			});
		},
		// 页面方法
		methods: {
			getElementPosition() {
				// 使用uni.createSelectorQuery创建选择器查询实例
				const query = uni.createSelectorQuery().in(this);
				let self = this;
				// 获取元素的位置信息
				query.select('.touch-clip-image') // 替换为你要获取位置信息的元素类名或选择器
					.boundingClientRect(rect => {
						// rect中包含了位置信息
						console.log('元素位置信息：', rect);
						// rect 包含了元素的位置、尺寸等信息
						// rect.top, rect.bottom, rect.left, rect.right, rect.width, rect.height
						self.positionX = rect.left
						self.positionY = rect.top
						console.log('positionY' + self.positionY + 'positionX' + self.positionX)
					})
					.exec();
			},
			// 初始化照片
			imageDraw(res) {
				const isWidth = res.width / this.width > res.height / this.height;
				if (isWidth) {
					this.imageCanvasWidth = this.width;
					this.imageCanvasHeight = res.height / (res.width / this.width);
				} else {
					this.imageCanvasHeight = this.height;
					this.imageCanvasWidth = res.width / (res.height / this.height);
				}
				this.image = res.path;
				this.getElementPosition();
			},
			// canvasPolygon绘制蒙层
			drawMonlayer() {
				this.canvasPolygon.rect(0, 0, this.width, this.height);
				this.canvasPolygon.fillStyle = 'rgba(85,255,0,' + this.alpha + ')';
				this.canvasPolygon.fill();
				this.canvasPolygon.draw();
				this.canvasPolygon.globalCompositeOperation = 'destination-out';
				this.canvasImage.beginPath();
				this.canvasPolygon.beginPath();
			},
			// 触摸开始
			touchstart(e) {
				let self = this;
				console.log('touchstart', e)
				if (!this.image) {
					return;
				}
				if (e.changedTouches) {
					e = e.changedTouches[0]
				}
				this.start = true
				this.touchX = parseFloat(e.pageX) - parseFloat(self.positionX);
				this.touchY = parseFloat(e.pageY) - parseFloat(self.positionY);
				this.canvasPolygon.arc(this.touchX, this.touchY, this.radius, 0, Math.PI * 2, true);
				this.canvasPolygon.fillStyle = 'rgba(85,255,0,' + this.alpha + ')';
				this.canvasPolygon.fill();
				this.canvasPolygon.draw(true);

				this.canvasImage.arc(this.touchX, this.touchY, this.radius, 0, Math.PI * 2, true);
				this.canvasImage.closePath();
			},
			// 触摸移动
			touchmove(e) {
				let self = this;
				console.log('touchmove', e)
				if (!this.image || !this.start) {
					return;
				}
				if (e.changedTouches) {
					e = e.changedTouches[0]
				}
				let X = parseFloat(e.pageX) - parseFloat(self.positionX);
				let Y = parseFloat(e.pageY) - parseFloat(self.positionY);
				console.log('pageX' + e.pageX + 'positionX' + self.positionX)
				console.log('pageY' + e.pageY + 'positionY' + self.positionY)
				console.log('移动坐标X轴' + X + 'Y轴' + Y)
				this.canvasPolygon.arc(X, Y, this.radius, 0, Math.PI * 2, true);
				this.canvasPolygon.fillStyle = 'rgba(85,255,0,' + this.alpha + ')';
				this.canvasPolygon.fill();
				this.canvasPolygon.draw(true);

				this.canvasImage.arc(X, Y, this.radius, 0, Math.PI * 2, true);
				this.canvasImage.closePath();
			},
			// 触摸结束
			touchend(e) {
				console.log('touchend', e)
				if (!this.image) {
					return;
				}
				this.start = false;
				this.isChoose = true;
				if (this.touchEndTodo) {
					this.polygon();
				}
			},
			// 裁剪的形状，主要函数
			polygon() {
				if (!this.image || !this.isChoose) {
					uni.showToast({
						title: '缺少图片或未选择裁剪区',
						icon: 'none'
					});
					return;
				}
				uni.showLoading({
					title: '裁剪中...',
					mask: true
				});
				this.canvasPolygon.clip();
				this.canvasImage.clip();
				this.canvasImage.drawImage(
					this.image,
					0,
					0,
					this.imageCanvasWidth,
					this.imageCanvasHeight
				);

				this.canvasImage.draw(false, () => {

					// 裁剪图像的区域
					let lOffset = this.width;
					let rOffset = 0;
					let tOffset = this.height;
					let bOffset = 0;
					uni.canvasGetImageData({
						canvasId: 'canvas-image',
						x: 0,
						y: 0,
						width: this.width,
						height: this.height,
						success: (res) => {
							let imgData = res.data;
							let threshold = 0;
							for (let i = 0; i < this.width; i++) {
								for (let j = 0; j < this.height; j++) {
									let pos = (i + this.width * j) * 4;
									if (imgData[pos + 3] > threshold) {
										// 这个条件说第j行第i列的像素不是透明的
										bOffset = Math.max(j, bOffset); // 找到不透明区域最底部的纵坐标
										rOffset = Math.max(i, rOffset); // 找到不透明区域的最右端
										tOffset = Math.min(j, tOffset); // 找到不透明区域的最上端
										lOffset = Math.min(i, lOffset); // 找到不透明区域的最左端
									}
								}
							}
							let t = setTimeout(() => {
								clearTimeout(t);
								uni.canvasToTempFilePath({
									x: lOffset,
									y: tOffset,
									width: rOffset - lOffset,
									height: bOffset - tOffset,
									fileType: 'png',
									canvasId: 'canvas-image',
									success: (res) => {
										uni.hideLoading();
										this.$emit('clipImageAfter', res
											.tempFilePath);
									},
									fail: (res) => {
										console.log(res);
									},
									complete: () => {}
								}, this);
							}, 300);
						}
					}, this);
				});
			},
			// 清除
			clearCanavas() {
				this.isChoose = false;
				this.canvasPolygon.restore();
				this.canvasImage.restore();
				this.canvasPolygon.globalCompositeOperation = 'source-over';
				this.canvasPolygon.draw();
				this.canvasImage.draw();
				this.drawMonlayer();
			}
		}
	};
</script>

<style lang='scss' scoped>
	.tool {
		color: #fff;
		background: #4E5058;
		border-radius: 4rpx 4rpx 4rpx 4rpx;
		display: flex;
		justify-content: space-around;
		align-items: center;
		width: 85%;
	}

	.touch-clip-image {
		z-index: 99999;
		position: fixed;

		/* left: 0;
	top: 0; */
		.text {
			width: 100%;
		}

		.canvas-polygon,
		.image-wrap {
			position: fixed;
			/* left: 0;
		top: 0; */
			z-index: 2;
		}

		.image-wrap {
			z-index: 0;
		}

		.canvas-image {
			position: fixed;
			left: 1000rpx;
			top: -1000rpx;
			z-index: 1;
		}
	}
</style>